#pragma once
#include "Dllexport.h"
#include <vector>
#include <string> 
#include "Listener.h"
#include "GUIDrawer.h"
#include "Handler.h"

namespace NBGUI
{
	enum GUIELEMENT
	{
		NONE = 0,
		CANVAS,
		BUTTON,
		IMAGE,
		PROGRESSBAR,
		TEXTBOX,
		SCROLLBAR,
		CHECKBOX,
		MENU,
		MENUITEM,
		TAB,
		SUBTAB,
		HANDLER,//for event
		INFO,//for parameter

		MAXELENUM

	};





	class GUIAPI ElementNode: public Listener//, public FunctionCaller
	{
	public:
		

		virtual ~ElementNode();
		ElementNode(GUIDrawer* drawer, const char* name, const char* eleText, int eleType = NONE, Rect& _rect = Rect());

		inline GUIELEMENT getElementType(){return elementType;}

		void setParent(ElementNode* p);
		ElementNode* attachElementNode(ElementNode* child);
		ElementNode* detachElementNode(ElementNode* child);
		ElementNode* detachElementNode( std::string elementName );
		inline bool hasChild(){return children.size() > 0;}
		std::vector<ElementNode*>& getChildren(){return children;}

		virtual void draw() = 0;
		
		inline std::string& name(){return elementName;}

		Rect& getRect(){return rect;}
		 
		virtual void buildVI(std::vector<Vertex>* vertices, std::vector<unsigned int>* indices,unsigned int screenWidth, unsigned int screenHeight){};
		//build the vertices and indices
		
		virtual void handleEvent(Event* e);


		void add(Handler& h){handlerList.push_back(h);}
		//virtual void doSomething(std::vector<info>& i){};
		virtual void doSomething(std::vector<info>& i, std::string& funcName)
		{
			if(funcName == std::string("setHide"))
				setHide(i.front().i == 1);
		};//todo use this one
		inline bool isInside(Event* e)
		{
			if (hide)
			{
				return false;
			}

			if(e->type >= MOUSE_MOVE || e->type <= MOUSE_DRAG )
			{
				vec2f mousePos = static_cast<MouseEvent*>(e)->pos;
				 if(mousePos.x >= rect.x && mousePos.x <= rect.x + rect.w &&
					 mousePos.y >= rect.y && mousePos.y <= rect.y + rect.h)
				 {
					 return true;
				 }
				 
			}
			return false;
		}

		inline ElementNode* findNode(ElementNode* start, std::string name)
		{
			if (start->name() ==  name )
			{
				return start;
			}
			int childrenCount = start->children.size();
			for (int i = 0; i < childrenCount; ++i)
			{
				ElementNode* result = findNode(start->children[i], name);
				if (result != nullptr)
				{
					return result;
				}

			}
			 
			return nullptr;
		}
		void setHide(bool b){hide = b;}
	protected:
		ElementNode* parent;
		std::vector<ElementNode*> children;

		GUIELEMENT elementType;
		std::string elementName;
		std::string elementText;
		strDrawingPack textDrawingPack;//for elementText drawing
		Rect rect;

		//for drawing
		unsigned int startIndex;
		unsigned int indexLen;
		GUIDrawer* pDrawer;
		bool hide;
		//


	public:
		std::vector<Handler> handlerList;
		std::vector<info> infoList;
	};
}

